﻿// Copyright (C) 2012 Jeff Tanner <jeff00seattle@gmail.com>
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
// 

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.ServiceProcess;
using System.Configuration;

using WindowsAzure_FileBackup_Common;
using WindowsAzure_REST;

namespace WindowsAzure_FileBackup_Console
{
    public partial class Console : Form
    {
        private Common common = null;

        public Console()
        {
            this.InitializeComponent();
            this.initialize();
        }

        private void initialize()
        {
            this.common = new Common();

            this.PrepareBackupButton.Enabled = false;
            this.GetBackupInfoButton.Enabled = false;
            this.SubmitFullActionButton.Enabled = false;

            StorageConnectionMode connectionMode = Common.WindowsAzureConnectionMode;

            this.StorageAccountNameTB.Text = Common.WindowsAzureStorageAccountName;
            this.StorageAccountKeyTB.Text = Common.WindowsAzureStorageAccountKey;
            this.BackupContainerNameTB.Text = Common.WindowsAzureStorageBlobContainerName;
            this.BackupLocalPathTB.Text = Common.WindowsAzureFileBackupRootDir;
            this.RecoveryLocalPathTB.Text = Common.WindowsAzureFileRecoveryRootDir;

            this.StorageAccountNameTB.Tag = !String.IsNullOrEmpty(this.StorageAccountNameTB.Text);
            this.StorageAccountKeyTB.Tag = !String.IsNullOrEmpty(this.StorageAccountKeyTB.Text);
            this.BackupContainerNameTB.Tag = !String.IsNullOrEmpty(this.BackupContainerNameTB.Text);
            this.BackupLocalPathTB.Tag = !String.IsNullOrEmpty(this.BackupLocalPathTB.Text);
            this.RecoveryLocalPathTB.Tag = !String.IsNullOrEmpty(this.RecoveryLocalPathTB.Text);

            this.StorageAccountNameTB.Validating += new System.ComponentModel.CancelEventHandler(storageAccountNameTB_Validating);
            this.StorageAccountKeyTB.Validating += new System.ComponentModel.CancelEventHandler(storageAccountKeyTB_Validating);
            this.BackupContainerNameTB.Validating += new System.ComponentModel.CancelEventHandler(backupContainerNameTB_Validating);
            this.BackupLocalPathTB.Validating += new System.ComponentModel.CancelEventHandler(backupLocalPathTB_Validating);
            this.RecoveryLocalPathTB.Validating += new System.ComponentModel.CancelEventHandler(recoveryLocalPathTB_Validating);

            this.StorageAccountNameTB.TextChanged += new System.EventHandler(this.txtBox_TextChanged);
            this.StorageAccountKeyTB.TextChanged += new System.EventHandler(this.txtBox_TextChanged);
            this.BackupContainerNameTB.TextChanged += new System.EventHandler(this.txtBox_TextChanged);
            this.BackupLocalPathTB.TextChanged += new System.EventHandler(this.txtBox_TextChanged);
            this.RecoveryLocalPathTB.TextChanged += new System.EventHandler(this.txtBox_TextChanged);

            System.OperatingSystem osInfo = System.Environment.OSVersion;
            System.Version osVersion = System.Environment.OSVersion.Version;

            this.ConnectionModeCloudRB.Checked = false;
            this.ConnectionModeLocalRB.Enabled = false;
            if (osInfo.Platform == PlatformID.Win32NT && osVersion.Major == 6)
            {
                this.ConnectionModeLocalRB.Enabled = true;

                if (StorageConnectionMode.Cloud == connectionMode)
                {
                    this.ConnectionModeCloudRB.Checked = true;
                }
                else
                {
                    this.ConnectionModeLocalRB.Checked = true;
                }
            }
            else
            {
                this.ConnectionModeCloudRB.Checked = true;
                this.ConnectionModeCloudRB.Enabled = false;
            }

            this.validateAll();

            this.getServiceStatus();
        }

        private void storageAccountNameTB_Validating(object sender, System.ComponentModel.CancelEventArgs e)
        {
            Control ctrl = (Control)sender;
            TextBox tb = (TextBox)sender;

            if (tb.Text.Length == 0)
            {
                this.StorageAccountNameEP.SetError(ctrl, "Provide Windows Azure Storage Account Name");
                tb.BackColor = Color.RosyBrown;
                tb.Tag = false;
            }
            else
            {
                this.StorageAccountNameEP.SetError(ctrl, "");
                tb.BackColor = System.Drawing.SystemColors.Window;
                tb.Tag = true;
            }

            this.validateAll();
        }

        private void storageAccountKeyTB_Validating(object sender, System.ComponentModel.CancelEventArgs e)
        {
            Control ctrl = (Control)sender;
            TextBox tb = (TextBox)sender;
            if (tb.Text.Length == 0)
            {
                this.StorageAccountKeyEP.SetError(ctrl, "Provide Windows Azure Storage Account Key");
                tb.BackColor = Color.RosyBrown;
                tb.Tag = false;
            }
            else
            {
                this.StorageAccountKeyEP.SetError(ctrl, "");
                tb.BackColor = System.Drawing.SystemColors.Window;
                tb.Tag = true;
            }

            this.validateAll();
        }


        private void backupContainerNameTB_Validating(object sender, System.ComponentModel.CancelEventArgs e)
        {
            Control ctrl = (Control)sender;
            TextBox tb = (TextBox)sender;
            if (tb.Text.Length == 0)
            {
                this.BackupContainerNameEP.SetError(ctrl, "Provide Windows Azure Storage Container Name");
                tb.BackColor = Color.RosyBrown;
                tb.Tag = false;
            }
            else
            {
                this.BackupContainerNameEP.SetError(ctrl, "");
                tb.BackColor = System.Drawing.SystemColors.Window;
                tb.Tag = true;
            }

            this.validateAll();
        }

        private void backupLocalPathTB_Validating(object sender, System.ComponentModel.CancelEventArgs e)
        {
            Control ctrl = (Control)sender;
            TextBox tb = (TextBox)sender;
            if (tb.Text.Length == 0)
            {
                this.BackupLocalPathEP.SetError(ctrl, "Provide backup directory path");
                tb.BackColor = Color.RosyBrown;
                tb.Tag = false;
            }
            else if (!Directory.Exists(tb.Text))
            {
                this.RecoveryLocalPathEP.SetError(ctrl, "Invalid backup directory path provided.");
                tb.BackColor = Color.RosyBrown;
                tb.Tag = false;
            }
            else if (tb.Text.ToLower().Equals(this.RecoveryLocalPathTB.Text.ToLower()))
            {
                this.RecoveryLocalPathEP.SetError(ctrl, "Backup directory path cannot be the same as Recovery directory path.");
                tb.BackColor = Color.RosyBrown;
                tb.Tag = false;
            }
            else
            {
                this.BackupLocalPathEP.SetError(ctrl, "");
                tb.BackColor = System.Drawing.SystemColors.Window;
                tb.Tag = true;
            }

            this.validateAll();
        }

        private void recoveryLocalPathTB_Validating(object sender, System.ComponentModel.CancelEventArgs e)
        {
            Control ctrl = (Control)sender;
            TextBox tb = (TextBox)sender;
            if (string.IsNullOrEmpty(tb.Text))
            {
                this.RecoveryLocalPathEP.SetError(ctrl, "Provide recovery directory path");
                tb.BackColor = Color.RosyBrown;
                tb.Tag = false;
            }
            else if (!Directory.Exists(tb.Text))
            {
                this.RecoveryLocalPathEP.SetError(ctrl, "Invalid recovery directory path provided.");
                tb.BackColor = Color.RosyBrown;
                tb.Tag = false;
            }
            else if (tb.Text.ToLower().Equals(this.BackupLocalPathTB.Text.ToLower()))
            {
                this.RecoveryLocalPathEP.SetError(ctrl, "Recovery directory path cannot be the same as Backup directory path.");
                tb.BackColor = Color.RosyBrown;
                tb.Tag = false;
            }
            else
            {
                this.RecoveryLocalPathEP.SetError(ctrl, "");
                tb.BackColor = System.Drawing.SystemColors.Window;
                tb.Tag = true;
            }

            this.validateAll();
        }
        private void txtBox_TextChanged(object sender, System.EventArgs e)
        {
            TextBox tb = (TextBox)sender;

            if (tb.Text.Length == 0)
            {
                tb.BackColor = Color.RosyBrown;
                tb.Tag = false;
            }
            else
            {
                tb.BackColor = System.Drawing.SystemColors.Window;
                tb.Tag = true;
            }

            this.validateAll();
        }

        private void validateAll()
        {
            bool buttonsEnabled
                = ((bool)(this.StorageAccountNameTB.Tag) &&
                  (bool)(this.StorageAccountKeyTB.Tag) &&
                  (bool)(this.BackupContainerNameTB.Tag) &&
                  (bool)(this.BackupLocalPathTB.Tag) &&
                  (bool)(this.RecoveryLocalPathTB.Tag));

            this.PrepareBackupButton.Enabled = buttonsEnabled;
            this.GetBackupInfoButton.Enabled = buttonsEnabled;
            this.SubmitFullActionButton.Enabled = buttonsEnabled;
            this.UpdateServiceButton.Enabled = buttonsEnabled;

            if (buttonsEnabled)
            {
                this.initializeBlobStorageAccess();
                this.getBackupInfo();
            }
        }

        ////////////////////////////////////////////////////////////////////////////////////////////////////
        /// <summary>   Event handler. Called by prepareBackupButton for click events. </summary>
        ///
        /// <param name="sender">   Source of the event. </param>
        /// <param name="e">        Event information. </param>
        ////////////////////////////////////////////////////////////////////////////////////////////////////

        private void prepareBackupButton_Click(object sender, EventArgs e)
        {
            this.initializeBlobStorageAccess();

            DirectoryInfo dirInfo = new DirectoryInfo(Common.WindowsAzureFileBackupRootDir.Replace(@"\", @"\\"));
            this.common.BackupDirectory(dirInfo);

            this.getBackupInfo();
        }

        ////////////////////////////////////////////////////////////////////////////////////////////////////
        /// <summary>   Event handler. Called by getBackupInfoButton for click events. </summary>
        ///
        /// <param name="sender">   Source of the event. </param>
        /// <param name="e">        Event information. </param>
        ////////////////////////////////////////////////////////////////////////////////////////////////////

        private void getBackupInfoButton_Click(object sender, EventArgs e)
        {
            this.getBackupInfo();
        }

        ////////////////////////////////////////////////////////////////////////////////////////////////////
        /// <summary>   Event handler. Called by syncBackupButton for click events. </summary>
        ///
        /// <param name="sender">   Source of the event. </param>
        /// <param name="e">        Event information. </param>
        ////////////////////////////////////////////////////////////////////////////////////////////////////

        private void submitFullActionButton_Click(object sender, EventArgs e)
        {
            Common.EnumServiceStatus serviceStatus = Common.EnumServiceStatus.Unknown;
            Common.GetServiceStatus(ConfigurationManager.AppSettings.Get("ServiceName"), out serviceStatus);
            if (serviceStatus == Common.EnumServiceStatus.ServiceInstalledStarted)
            {
                Common.StopService(Common.WindowsAzureStorageAccountName, 1000);
                this.ServiceStatusOutL.Text = Common.GetServiceStatus(ConfigurationManager.AppSettings.Get("ServiceName"), out serviceStatus);
            }

            this.initializeBlobStorageAccess();
           
            if (this.RecoverBackupRB.Checked)
            {
                DirectoryInfo dirInfo = new DirectoryInfo(Common.WindowsAzureFileRecoveryRootDir.Replace(@"\", @"\\"));
                Common.DeleteAllFiles(dirInfo);
                this.common.RecoveryDirectory(dirInfo);
            }
            else if (this.CloudBackupRB.Checked)
            {
                DirectoryInfo dirInfo = new DirectoryInfo(Common.WindowsAzureFileBackupRootDir.Replace(@"\", @"\\"));
                Common.DeleteContainerBlobs();
                this.common.BackupDirectory(dirInfo);
            }

            this.getBackupInfo();
        }

        private void getServiceStatus()
        {
            Common.EnumServiceStatus status = Common.EnumServiceStatus.Unknown;
            this.ServiceStatusOutL.Text = Common.GetServiceStatus(ConfigurationManager.AppSettings.Get("ServiceName"), out status);
        }

        private void getBackupInfo()
        {
            // Count files
            DirectoryInfo diBackup = new DirectoryInfo(Common.WindowsAzureFileBackupRootDir.Replace(@"\", @"\\"));
            int filesCountBackup = 0;
            this.common.BackupDirectoryCount(diBackup, ref filesCountBackup);
            this.LocalBackupFileCountOutL.Text = filesCountBackup.ToString();

            DirectoryInfo diRecovery = new DirectoryInfo(Common.WindowsAzureFileRecoveryRootDir.Replace(@"\", @"\\"));
            int filesCountRecovery = 0;
            this.common.BackupDirectoryCount(diRecovery, ref filesCountRecovery);
            this.LocalRecoveryFileCountOutL.Text = filesCountRecovery.ToString();

            // Count blobs
            List<string> blobs
                = Common.BlobREST.ListBlobs(Common.WindowsAzureStorageBlobContainerName);

            this.CloudBackupFileCountOutL.Text = blobs.Count.ToString();
        }

        ////////////////////////////////////////////////////////////////////////////////////////////////////
        /// <summary>   Event handler. Called by updateServiceButton for click events. </summary>
        ///
        /// <param name="sender">   Source of the event. </param>
        /// <param name="e">        Event information. </param>
        ////////////////////////////////////////////////////////////////////////////////////////////////////

        private void updateServiceButton_Click(object sender, EventArgs e)
        {
            if (this.ServiceStopRB.Checked)
            {
                Common.StopService(ConfigurationManager.AppSettings.Get("ServiceName"), 1000);
            }
            else if (this.ServiceStartRB.Checked)
            {
                Common.StartService(ConfigurationManager.AppSettings.Get("ServiceName"), 1000);
            }
            else if (this.ServiceRestartRB.Checked)
            {
                Common.RestartService(ConfigurationManager.AppSettings.Get("ServiceName"), 1000);
            }

            getServiceStatus();
        }

        private void initializeBlobStorageAccess()
        {
            Common.WindowsAzureStorageAccountName = this.StorageAccountNameTB.Text;
            Common.WindowsAzureStorageAccountKey = this.StorageAccountKeyTB.Text;
            Common.WindowsAzureStorageBlobContainerName = this.BackupContainerNameTB.Text;
            Common.WindowsAzureFileBackupRootDir = this.BackupLocalPathTB.Text;
            Common.WindowsAzureFileRecoveryRootDir = this.RecoveryLocalPathTB.Text;

            Common.WindowsAzureConnectionMode = StorageConnectionMode.Cloud;
            if (this.ConnectionModeLocalRB.Enabled && this.ConnectionModeLocalRB.Checked)
            {
                Common.WindowsAzureConnectionMode = StorageConnectionMode.Local;
            }

            Common.SetupBlobREST();

            this.common.BlobContainerCreate();
        }
    }
}
